package com.ruicar.afs.cloud.product.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ruicar.afs.cloud.bizcommon.algorithm.enums.CalculateType;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.uid.AfsSequenceGenerator;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.rules.RuleHelper;
import com.ruicar.afs.cloud.common.rules.constants.RuleRunEnum;
import com.ruicar.afs.cloud.common.rules.dto.RuleResult;
import com.ruicar.afs.cloud.product.condition.ExtrasProgramConfigCondition;
import com.ruicar.afs.cloud.product.condition.ProductPlanCondition;
import com.ruicar.afs.cloud.product.condition.ProductPrototypeCondition;
import com.ruicar.afs.cloud.product.dto.CheckProductInfoDto;
import com.ruicar.afs.cloud.product.entity.*;
import com.ruicar.afs.cloud.product.enums.*;
import com.ruicar.afs.cloud.product.mapper.ProductPlanMapper;
import com.ruicar.afs.cloud.product.mq.send.CommissionSystemSender;
import com.ruicar.afs.cloud.product.service.*;
import com.ruicar.afs.cloud.product.util.ProductParmsConfig;
import com.ruicar.afs.cloud.product.vo.*;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author changyu.gui
 * @version 1.0
 * @date 2020/5/11 20:49
 */
@Service("productPlanService")
@AllArgsConstructor
@ConditionalOnProperty(prefix = "com.ruicar.afs.cloud.mq.rabbit",name="enable")
public class ProductPlanServiceImpl extends ServiceImpl<ProductPlanMapper, ProductPlan> implements ProductPlanService {

    private static final Logger logger = LoggerFactory.getLogger(ProductPlanServiceImpl.class);

    private final ProductRuleInfoService productRuleInfoService;
    private final ProductPlanAtomService productPlanAtomService;
    private final ProductPlanRateService productPlanRateService;
    private final ExtrasProgramService extrasProgramService;
    private final ProductDiscountPlanService productDiscountPlanService;
    private final ProductDiscountConfigService productDiscountConfigService;
    private final ExtrasProgramConfigService extrasProgramConfigService;
    private final ProductPlanRepayService productPlanRepayService;
    private final ExtrasProjectService extrasService;
    private final LprConfigurationService lprConfigurationService;
    private final SchemeRiskService planService;
    private final SchemeFinanceService financePlanService;
    private final SchemeLaunchService launchPlanService;
    private final ProductTemplateService templateService;
    private final ProductParmsConfig productParmsConfig;
    private final CommissionSystemSender commissionSystemSender;
    private final AfsSequenceGenerator afsSequenceGenerator;

    @Override
    public List<ProductPlanVo> getVueInfo(ProductPlanCondition planCondition) {
        return this.baseMapper.getVueJs(planCondition);
    }

    @Override
    public IPage<ProductPrototypeVo> queryProductPrototypeList(Page page, ProductPlanCondition planCondition) {
        IPage<ProductPrototypeVo> iPage = this.baseMapper.queryProductPrototypeList(page, planCondition);
        iPage.getRecords().forEach(productPrototypeVo -> {
            if (StringUtils.isNotBlank(productPrototypeVo.getCarNature())) {//车辆属性
                String value = productPrototypeVo.getCarNature().replace("[", "").replace("]", "").replace(" ", "");
                productPrototypeVo.setCarNatures(value.split(","));
            }
            if (StringUtils.isNotBlank(productPrototypeVo.getCarType())) {//车辆类型
                String value = productPrototypeVo.getCarType().replace("[", "").replace("]", "").replace(" ", "");
                productPrototypeVo.setCarTypes(value.split(","));
            }
            if (StringUtils.isNotBlank(productPrototypeVo.getBusinessType())) {//业务类型
                String value = productPrototypeVo.getBusinessType().replace("[", "").replace("]", "").replace(" ", "");
                productPrototypeVo.setBusinessTypes(value.split(","));
            }
        });
        return iPage;
    }

    /**
     * 获取产品投放命中的产品
     *
     * @return
     */
    public IPage<ProductPlan> getProductPlanListByLaunch(CheckProductInfoDto info) {

        //结果返回值
        IPage<ProductPlan> productPlanList = null;

        //得到命中的规则组
        List launchList = new ArrayList();
        try {
            JSONObject json = JSON.parseObject(JSON.toJSONString(info));
            List<RuleResult> ruleRunResult = RuleHelper.runRule(json, AfsEnumUtil.key(RuleGroupEnum.LAUNCHPLAN), false, RuleRunEnum.PARALLEL).getResults();//得到运行结果
            if (ruleRunResult.size() > 0) {//空直接返回
                //规则组结果转化
                List ruleNoList = Lists.transform(ruleRunResult, (ruleResult) -> {
                    return ruleResult.getRuleNo();
                });
                //找到所有的适用规则信息
                List<ProductRuleInfo> ruleInfoList = productRuleInfoService.list(Wrappers.<ProductRuleInfo>query().lambda()
                        .eq(ProductRuleInfo::getFitScope, AfsEnumUtil.key(FitScope.LAUNCHPLAN))//适用场景=产品投放方案
                        .and(wraper -> wraper
                                .le(ProductRuleInfo::getStartTime, DateUtil.endOfDay(DateUtil.date()))//开始时间小于等于当前时间
                                .or()
                                .isNull(ProductRuleInfo::getStartTime)//开始时间为空
                        )
                        .and(wraper -> wraper
                                .ge(ProductRuleInfo::getEndTime, DateUtil.beginOfDay(DateUtil.date()))//结束时间大于等于当前时间
                                .or()
                                .isNull(ProductRuleInfo::getEndTime)//结束时间为空
                        )
                        .in(ProductRuleInfo::getId, ruleNoList)//匹配规则组id
                );

                if (ruleInfoList.size() > 0) {//空直接返回
                    launchList = Lists.transform(ruleInfoList, (productRuleInfo) -> {
                        return productRuleInfo.getPlanId();
                    });
                }
            }
        } catch (Exception e) {
            return null;
        }

        //接口传输的特殊值
        CheckAtomInfoVo atomInfo = info.getAtomInfo();
        String businessType = (String) atomInfo.getBusinessType();
        String carNature = (String) atomInfo.getCarNature();
        String carType = (String) atomInfo.getCarType();
        //判空处理
        if (StringUtils.isEmpty(businessType) || StringUtils.isEmpty(carNature) || StringUtils.isEmpty(carType)) {
            return null;
        }
        //业务类型
        List<ProductPlanAtom> listBusinessType = this.getProductPlanDataList(businessType, AfsEnumUtil.key(ProductAtomEnum.BUSINESSTYPE));
        if (listBusinessType.size() == 0) {//空直接返回
            return null;
        }
        List businessTypeList = Lists.transform(listBusinessType, (productPlanData) -> {
            return productPlanData.getProductPlanId();
        });
        //车辆属性
        List<ProductPlanAtom> listCarNature = this.getProductPlanDataList(carNature, AfsEnumUtil.key(ProductAtomEnum.CARNATURE));
        if (listCarNature.size() == 0) {//空直接返回
            return null;
        }
        List carNatureList = Lists.transform(listCarNature, (productPlanData) -> {
            return productPlanData.getProductPlanId();
        });
        //车辆类型
        List<ProductPlanAtom> listCarType = this.getProductPlanDataList(carType, AfsEnumUtil.key(ProductAtomEnum.CARTYPE));
        if (listCarType.size() == 0) {//空直接返回
            return null;
        }
        List carTypeList = Lists.transform(listCarType, (productPlanData) -> {
            return productPlanData.getProductPlanId();
        });
        //接口传输的分页
        int pageNo = info.getPageNo();//页码
        int pageSize = info.getPageSize();//每页多少条数据

        //判空处理
        if (businessTypeList==null || carNatureList==null || carTypeList==null || launchList==null) {
            return null;
        }

        //查询当前上线的产品
        productPlanList = this.page(new Page(pageNo, pageSize), (Wrapper<ProductPlan>) Wrappers.<ProductPlan>query().lambda()
                .eq(ProductPlan::getStatus, AfsEnumUtil.key(ProductOnlineStatus.GO_ONLINE))//状态=上线
                .like(StringUtil.isNotEmpty(info.getProductName()),ProductPlan::getProductName,info.getProductName())//产品名称
                .le(ProductPlan::getStartTime, DateUtil.endOfDay(DateUtil.date()))//开始时间小于等于当前时间
                .ge(ProductPlan::getEndTime, DateUtil.beginOfDay(DateUtil.date()))//结束时间大于等于当前时间
                .in(ProductPlan::getId, businessTypeList)//匹配产品id
                .in(ProductPlan::getId, carNatureList)//匹配产品id
                .in(ProductPlan::getId, carTypeList)//匹配产品id
                .in(ProductPlan::getLaunchPlanId, launchList)//匹配产品投放id
        );

        return productPlanList;
    }

    /**
     * @param atomValue      原子值
     * @param productAtomKey 原子key
     * @return
     * @Description 查询产品原子数据集
     */
    public List<ProductPlanAtom> getProductPlanDataList(String atomValue, String productAtomKey) {
        List<ProductPlanAtom> list = productPlanAtomService.list(Wrappers.<ProductPlanAtom>query().lambda()
                .eq(ProductPlanAtom::getProductAtomKey, productAtomKey)
                .like(ProductPlanAtom::getAtomValue, atomValue)
        );
        return list;
    }


    /**
     * @param info
     * @return
     * @Description 查询信息校验
     */
    @Override
    public List<String> checkProductInfo(CheckProductInfoDto info) {

        List resultList = new ArrayList();
        //对规则对比信息进行处理
        JSONObject json = JSON.parseObject(JSON.toJSONString(info));
        //组装附加项数据
        List<ExtrasInfo> list = extrasService.list(Wrappers.<ExtrasInfo>query().lambda().orderByAsc());
        JSONObject checkExtrasInfo = JSON.parseObject(JSON.toJSONString(new CheckExtrasInfoVo()));
        for (ExtrasInfo extrasInfo : list) {
            json.put("ExtrasInfo" + extrasInfo.getExtrasProjectNo(), checkExtrasInfo);
        }
        List<CheckExtrasInfoVo> extrasInfoList = info.getExtrasInfoList();
        if (extrasInfoList != null && extrasInfoList.size() > 0) {
            for (CheckExtrasInfoVo checkExtrasInfoVo : extrasInfoList) {
                json.put("ExtrasInfo" + checkExtrasInfoVo.getFinanceItemCode(), JSON.parseObject(JSON.toJSONString(checkExtrasInfoVo)));
            }
        }
        //获取主产品融资信息
        CheckCostInfoVo mainVo = info.getMainProductInfo();
        //获取主产品ID
        Long mainProductId = mainVo.getProductId();
        ProductPlan productPlan = this.getById(mainProductId);

        //校验产品是否过期
        if("yes".equals(info.getHasProductValid()) && (productPlan.getStartTime().getTime()> DateUtil.date().getTime() || productPlan.getEndTime().getTime()< DateUtil.date().getTime())){
            resultList.add("此产品已经过期");
            return resultList;
        }

        //最小首付比例校验
        ProductPlanAtom downPayRatioMin = productPlanAtomService.getProductPlanData(productPlan.getId(), AfsEnumUtil.key(ProductAtomEnum.DOWNPAYRATIOMIN));
        if (new BigDecimal(downPayRatioMin.getAtomValue()).compareTo(mainVo.getDownPayScale()) > 0) {
            resultList.add("产品设定最小首付比例为" + downPayRatioMin.getAtomValue());
        }

        //根据产品ID查询融资校验ID
        String financeId = productPlan.getFinancePlanId();
        //得到命中的规则组
        //确定存在规则
        List<ProductRuleInfo> ruleInfoList = productRuleInfoService.list(Wrappers.<ProductRuleInfo>query().lambda()
                .eq(ProductRuleInfo::getFitScope, AfsEnumUtil.key(FitScope.FINANCEPLAN))//适用场景
                .eq(ProductRuleInfo::getPlanId, financeId)//方案ID
                .ne(ProductRuleInfo::getRuleId, "")//规则ID不为空
        );
        if (ruleInfoList.size() > 0) {
            resultList = this.getRuleInfo(resultList, financeId.toString(), json, AfsEnumUtil.key(FitScope.FINANCEPLAN));
        }

        //根据产品ID查询附加方案ID
        String extrasPlanId = productPlan.getExtrasPlanId();
        //得到命中的规则组
        if (extrasPlanId != null) {
            List<ProductRuleInfo> ruleInfoListFinance = productRuleInfoService.list(Wrappers.<ProductRuleInfo>query().lambda()
                    .eq(ProductRuleInfo::getFitScope, AfsEnumUtil.key(FitScope.EXTRASPLAN))//适用场景
                    .eq(ProductRuleInfo::getPlanId, extrasPlanId)//方案ID
                    .ne(ProductRuleInfo::getRuleId, "")//规则ID不为空
            );
            if (ruleInfoListFinance.size() > 0) {
                resultList = this.getRuleInfo(resultList, extrasPlanId.toString(), json, AfsEnumUtil.key(FitScope.EXTRASPLAN));
            }
        }
        return resultList;
    }

    /**
     * @param info
     * @return
     * @Description 风控准入校验
     */
    @Override
    public List<String> chenkRiskInfo(CheckProductInfoDto info) {

        //得到命中的规则组
        List resultList = new ArrayList();
        //获取主产品融资信息
        CheckCostInfoVo mainVo = info.getMainProductInfo();
        //获取主产品ID
        Long mainProductId = mainVo.getProductId();
        ProductPlan productPlan = this.getById(mainProductId);
        //校验产品是否过期
        if("yes".equals(info.getHasProductValid()) && (productPlan.getStartTime().getTime()> DateUtil.date().getTime() || productPlan.getEndTime().getTime()< DateUtil.date().getTime())){
            resultList.add("此产品已经过期");
            return resultList;
        }

        //对规则对比信息进行处理
        JSONObject json = JSON.parseObject(JSON.toJSONString(info));
        //组装附加项数据
        List<ExtrasInfo> list = extrasService.list(Wrappers.<ExtrasInfo>query().lambda().orderByAsc());
        JSONObject checkExtrasInfo = JSON.parseObject(JSON.toJSONString(new CheckExtrasInfoVo()));
        for (ExtrasInfo extrasInfo : list) {
            json.put("ExtrasInfo" + extrasInfo.getExtrasProjectNo(), checkExtrasInfo);
        }
        List<CheckExtrasInfoVo> extrasInfoList = info.getExtrasInfoList();
        if (extrasInfoList != null && extrasInfoList.size() > 0) {
            for (CheckExtrasInfoVo checkExtrasInfoVo : extrasInfoList) {
                json.put("ExtrasInfo" + checkExtrasInfoVo.getFinanceItemCode(), JSON.parseObject(JSON.toJSONString(checkExtrasInfoVo)));
            }
        }
        //确定存在规则
        List<ProductRuleInfo> ruleInfoList = productRuleInfoService.list(Wrappers.<ProductRuleInfo>query().lambda()
                .eq(ProductRuleInfo::getFitScope, AfsEnumUtil.key(FitScope.RISKCONTROL))//适用场景
                .ne(ProductRuleInfo::getRuleId, "")//规则ID不为空
        );
        if (ruleInfoList.size() > 0) {
            resultList = getRuleInfo(resultList, AfsEnumUtil.key(RuleGroupEnum.RISKCONTROL), json, AfsEnumUtil.key(FitScope.RISKCONTROL));
        }
        return resultList;
    }


    /**
     * @param resultList 结果集
     * @param ruleGroup  规则组
     * @param json       规则信息
     * @return
     * @Description 得到反向命中的结果集
     */
    public List getRuleInfo(List resultList, String ruleGroup, JSONObject json, String fitScope) {
        try {
            List<RuleResult> ruleRunResult = RuleHelper.runByGroup(json, ruleGroup, false, RuleRunEnum.PARALLEL, true).getResults();//得到运行结果
            for (RuleResult ruleResult : ruleRunResult) {
                if ("false".equals(ruleResult.getResult().toString())) {
                    //找到所有的适用规则信息
                    ProductRuleInfo productRuleInfo = productRuleInfoService.getOne(Wrappers.<ProductRuleInfo>query().lambda()
                                    .eq(ProductRuleInfo::getFitScope, fitScope)//适用场景
                                    .eq(ProductRuleInfo::getId, ruleResult.getRuleNo())//匹配规则组id
                            , false
                    );
                    if (AfsEnumUtil.key(StatusEnum.YES).equals(productRuleInfo.getRuleStatus())) {
                        resultList.add(productRuleInfo.getOutputInfo());
                    }
                }
            }
        } catch (Exception e) {
            if (AfsEnumUtil.key(FitScope.RISKCONTROL).equals(fitScope)) {
                resultList.add("产品风控准入规则配置错误");
            } else if (AfsEnumUtil.key(FitScope.FINANCEPLAN).equals(fitScope)) {
                resultList.add("产品融资校验方案规则配置错误");
            } else if (AfsEnumUtil.key(FitScope.EXTRASPLAN).equals(fitScope)) {
                resultList.add("产品附加贷方案规则配置错误");
            } else {
                resultList.add("产品方案规则配置错误");
            }
        }
        return resultList;
    }

    /**
     * 获取产品利率
     *
     * @param info
     * @return
     */
    @Override
    public JSONObject getcustomerrate(CheckProductInfoDto info) {

        //返回最终结果初始化
        JSONObject jsonResult = new JSONObject();
        //规则命中信息转化
        JSONObject json = JSON.parseObject(JSON.toJSONString(info));

        //获取主产品信息
        CheckCostInfoVo voMain = info.getMainProductInfo();
        ProductPlan productPlanMain = this.getById(info.getId());

        //查询主产品利率
        ProductPlanRate productPlanRateMain = this.getProductPlanRate(productPlanMain.getId(), voMain.getLoanTerm());
        //计算出最终利率信息
        if (productPlanRateMain != null) {
            productPlanRateMain = this.getProductPlanRateByIsRisk(productPlanRateMain, json, productPlanMain);//风险定价
            productPlanRateMain = this.getProductPlanRateByRateType(productPlanRateMain, productPlanMain);//利率类型
            jsonResult.put("main", JSON.parseObject(JSON.toJSONString(productPlanRateMain)));

            //获取贴息数据
            ProductPlanAtom discountType = productPlanAtomService.getProductPlanData(productPlanMain.getId(), AfsEnumUtil.key(ProductAtomEnum.DISCOUNTTYPE));
            Map mainProductInfo = new HashMap();
            mainProductInfo = this.getDiscountOption(discountType, productPlanMain.getDiscountPlanId(), mainProductInfo, json);//贴息信息
            jsonResult.put("mainDiscount", mainProductInfo);
        }

        //查询子产品利率
        CheckCostInfoVo voSon = info.getAddProductInfo();
        if (voSon != null) {
            ProductPlan productPlanSon = this.getById(voSon.getProductId());
            if (productPlanSon != null) {
                //查询产品对应的一条利率
                ProductPlanRate productPlanRateSon = this.getProductPlanRate(productPlanSon.getId(), voSon.getLoanTerm());
                //计算出最终利率信息，风险定价和浮动使用主产品信息
                if (productPlanRateSon != null) {
                    productPlanRateSon = this.getProductPlanRateByRateType(productPlanRateSon, productPlanSon);//利率类型
                    jsonResult.put("son", JSON.parseObject(JSON.toJSONString(productPlanRateSon)));

                    //获取贴息数据
                    ProductPlanAtom discountType = productPlanAtomService.getProductPlanData(productPlanSon.getId(), AfsEnumUtil.key(ProductAtomEnum.DISCOUNTTYPE));
                    Map mainProductInfo = new HashMap();
                    mainProductInfo = this.getDiscountOption(discountType, productPlanSon.getDiscountPlanId(), mainProductInfo, json);//贴息信息
                    jsonResult.put("sonDiscount", mainProductInfo);
                }
            }
        }
        return jsonResult;
    }

    /**
     * @param productPlanRate 利率表
     * @param json            规则命中信息
     * @param productPlanMain 产品表
     * @return
     * @Description 根据风险定价得到最终的利率信息
     */
    public ProductPlanRate getProductPlanRateByIsRisk(ProductPlanRate productPlanRate, JSONObject json, ProductPlan productPlanMain) {
        //是否风险定价数据
        ProductPlanAtom isRiskPricing = productPlanAtomService.getProductPlanData(productPlanMain.getId(), AfsEnumUtil.key(ProductAtomEnum.ISRISKPRICING));
        if (AfsEnumUtil.key(StatusEnum.YES).equals(isRiskPricing.getAtomValue())) {
            //客户利率
            BigDecimal custRate = this.getRiskPricing(json, productPlanRate.getCustRate(), productPlanMain.getRiskPlanId().toString());
            productPlanRate.setCustRate(custRate);//调整风险定价之后的利率值
            //结算利率
            BigDecimal clearRate = this.getRiskPricing(json, productPlanRate.getClearRate(), productPlanMain.getRiskPlanId().toString());
            productPlanRate.setClearRate(clearRate);//调整风险定价之后的利率值
        }
        return productPlanRate;
    }

    /**
     * @param productPlanRate 利率表
     * @param json            规则命中信息
     * @param productPlan     产品表
     * @return
     * @Description 根据利率类型得到最终的利率信息
     */
    public ProductPlanRate getProductPlanRateByRateType(ProductPlanRate productPlanRate, ProductPlan productPlan) {
        //利率类型数据
        ProductPlanAtom rateType = productPlanAtomService.getProductPlanData(productPlan.getId(), AfsEnumUtil.key(ProductAtomEnum.RATETYPE));
        if (AfsEnumUtil.key(StatusType.FLOAT).equals(rateType.getAtomValue())) {
            Double lprRate = lprConfigurationService.getLprNew(productPlanRate.getLoanPeriodStart(), productPlanRate.getLoanPeriodEnd());//得到LPR利率值
            BigDecimal lprCalRate = productPlanRate.getAddPointValue().divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(lprRate));//调整LRP之后的利率值
            productPlanRate.setCustRate(lprCalRate.setScale(2, BigDecimal.ROUND_HALF_UP));//四舍五入
            productPlanRate.setClearRate(productPlanRate.getCustRate());//结算利率使用客户利率
        }
        return productPlanRate;
    }

    /**
     * @param productID 产品ID
     * @param loanTerm  贷期
     * @return
     * @Description 查询产品对应的一条利率
     */
    public ProductPlanRate getProductPlanRate(Long productID, int loanTerm) {
        ProductPlanRate productPlanRateMain = productPlanRateService.getOne((Wrapper<ProductPlanRate>) Wrappers.<ProductPlanRate>query().lambda()
                        .eq(ProductPlanRate::getProductPlanId, productID)//产品ID
                        .le(ProductPlanRate::getLoanPeriodStart, loanTerm)//开始贷期小于贷期
                        .ge(ProductPlanRate::getLoanPeriodEnd, loanTerm)//结束贷期大于贷期
                , false
        );
        return productPlanRateMain;
    }

    /**
     * @param json     规则信息
     * @param custRate 客户利率
     * @param groupNo  规则组
     * @return
     * @Description 得到风险定价之后的客户利率
     */
    public BigDecimal getRiskPricing(JSONObject json, BigDecimal custRate, String groupNo) {
        //得到命中的规则组
        List<RuleResult> ruleRunResult = RuleHelper.runRule(json, groupNo, false, RuleRunEnum.PARALLEL).getResults();//得到运行结果
        if (ruleRunResult.size() > 0) {//空直接返回
            //规则组结果转化
            List ruleNoList = Lists.transform(ruleRunResult, (ruleResult) -> {
                return ruleResult.getRuleNo();
            });
            //找到所有的适用规则信息
            List<ProductRuleInfo> ruleInfoList = productRuleInfoService.list(Wrappers.<ProductRuleInfo>query().lambda()
                    .eq(ProductRuleInfo::getFitScope, AfsEnumUtil.key(FitScope.RISKPLAN))//适用场景=风险定价方案
                    .in(ProductRuleInfo::getId, ruleNoList)//匹配规则组id
            );
            //固定值
            BigDecimal fixedOne = BigDecimal.ONE;
            //加点值
            BigDecimal addLittle = BigDecimal.ZERO;
            //系数值
            BigDecimal coefficient = BigDecimal.ZERO;
            //规则信息
            for (ProductRuleInfo productRuleInfo : ruleInfoList) {
                if (AfsEnumUtil.key(StatusType.COEFFICIENT).equals(productRuleInfo.getInterestRateType())) {//利率取值方式=0,系数值
                    coefficient = coefficient.add(custRate.multiply(productRuleInfo.getInterestRateValue().subtract(fixedOne)));//系数值=系数值+客户利率*（系数-1）
                } else if (AfsEnumUtil.key(StatusType.ADDLITTLE).equals(productRuleInfo.getInterestRateType())) {
                    addLittle = addLittle.add(productRuleInfo.getInterestRateValue());//加点值 = 加点值 + 加点
                }
            }
            //客户利率 = 客户利率+系数值+加点值
            custRate = custRate.add(coefficient).add(addLittle);
        }
        return custRate;
    }

    /**
     * 根据主产品ID查询所有产品信息
     *
     * @param info
     * @return
     */
    public Map getProductDetails(CheckProductInfoDto info) {
        //得到主产品ID
        Long productPlanId = info.getId();
        //主产品信息
        Map mainProductInfo = this.getProductPlanDetail(info, productPlanId);
        //结果集
        Map resultMap = new HashMap();
        resultMap.put("mainProductInfo", mainProductInfo);

        //获取是否附加贷数据
        ProductPlanAtom isAddLoan = productPlanAtomService.getProductPlanData(productPlanId, AfsEnumUtil.key(ProductAtomEnum.ISADDLOAN));
        if (isAddLoan != null) {
            //存在附加贷
            if (AfsEnumUtil.key(StatusEnum.YES).equals(isAddLoan.getAtomValue())) {

                //根据产品ID获取产品明细信息
                ProductPlan productPlan = this.getById(productPlanId);
                //附加方案ID
                String extrasPlanId = productPlan.getExtrasPlanId();
                //附加方案详情
                ExtrasProgramInfo extrasProgramInfo = extrasProgramService.getById(extrasPlanId);
                //是否存在子产品
                String isProduct = extrasProgramInfo.getIsProduct();
                Map sonMap = new HashMap();
                if (AfsEnumUtil.key(StatusEnum.YES).equals(isProduct)) {//子产品是否为空
                    //子产品ID
                    Long sonProductPlanId = extrasProgramInfo.getProductPlanId();
                    sonMap = this.getProductPlanDetail(info, sonProductPlanId);
                } else {
                    sonMap = this.getProductPlanDetail(info, productPlanId);
                }
                //查询附加项目列表
                ExtrasProgramConfigCondition extrasProgramConfig = new ExtrasProgramConfigCondition();
                extrasProgramConfig.setExtrasPlanId(extrasPlanId);
                List<ExtrasProgramInfoVo> ExtrasProgramInfoVoList = extrasProgramConfigService.getExtrasConfigProgramList(extrasProgramConfig);

                //数据组装
                sonMap.put("itemList", buildTree(ExtrasProgramInfoVoList));
                sonMap.put("extrasInfo", JSON.parseObject(JSON.toJSONString(extrasProgramInfo), Map.class));

                resultMap.put("addProductInfo", sonMap);
            }
            resultMap.put("isAdditional", isAddLoan.getAtomValue());
        }
        return resultMap;
    }

    /**
     * 根据产品ID获取产品相关信息
     *
     * @param productPlanId 产品
     * @return
     */
    public Map getProductPlanDetail(CheckProductInfoDto info, Long productPlanId) {

        //对规则对比信息进行处理
        JSONObject json = JSON.parseObject(JSON.toJSONString(info));
        //根据产品ID获取产品明细信息
        ProductPlan productPlan = this.getById(productPlanId);
        //根据产品ID获取产品利率列表
        List<ProductPlanRate> productPlanRatelist = productPlanRateService.list(Wrappers.<ProductPlanRate>query().lambda().eq(ProductPlanRate::getProductPlanId, productPlanId));
        //根据产品ID获取产品原子数据列表
        List<ProductPlanAtom> productPlanAtomList = productPlanAtomService.list(Wrappers.<ProductPlanAtom>query().lambda().eq(ProductPlanAtom::getProductPlanId, productPlanId));
        Map productPlanDataMap = new HashMap();
        for (ProductPlanAtom productPlanAtom : productPlanAtomList) {
            productPlanDataMap.put(productPlanAtom.getProductAtomKey(), productPlanAtom.getAtomValue());
        }

        //获取贴息数据
        ProductPlanAtom discountType = productPlanAtomService.getProductPlanData(productPlanId, AfsEnumUtil.key(ProductAtomEnum.DISCOUNTTYPE));
        //获取还款方式数据
        ProductPlanAtom repaymentType = productPlanAtomService.getProductPlanData(productPlanId, AfsEnumUtil.key(ProductAtomEnum.REPAYMENTTYPE));

        //返回的结果集
        Map mainProductInfo = new HashMap();
        mainProductInfo.put("baseInfo", JSON.parseObject(JSON.toJSONString(productPlan), Map.class));//基本信息
        mainProductInfo.put("detailInfo", productPlanDataMap);//产品原子数据详情
        mainProductInfo.put("rateList", productPlanRatelist);//利率列表

        mainProductInfo = this.getDiscountOption(discountType, productPlan.getDiscountPlanId(), mainProductInfo, json);//贴息信息
        mainProductInfo = this.getIsTail(repaymentType, mainProductInfo);//是否存在尾款
        mainProductInfo = this.getAlgorithmType(repaymentType, discountType, mainProductInfo);//算法方式
        mainProductInfo = this.getRepaymentData(repaymentType, mainProductInfo, productPlanId);//还款方式参数数据

        return mainProductInfo;
    }

    /**
     * @param discountType   贴息数据
     * @param discountPlanId 贴息方案ID
     * @param map            返回集
     * @return
     * @Description 获取贴息信息并返回
     */
    public Map getDiscountOption(ProductPlanAtom discountType, String discountPlanId, Map map, JSONObject json) {
        if (discountType != null) {
            if ( AfsEnumUtil.key(DiscountCategory.YES).equals(discountType.getAtomValue()) ||  AfsEnumUtil.key(DiscountCategory.Flexible).equals(discountType.getAtomValue())) {
                //根据产品贴息方案ID查询贴息方案
                ProductDiscountPlan productDiscountPlan = productDiscountPlanService.getById(discountPlanId);
                //根据贴息方案ID查询补贴方列表
                List<ProductDiscountSubsidy> listProductDiscountSubsidy = productDiscountConfigService.list(Wrappers.<ProductDiscountSubsidy>query().lambda()
                        .eq(ProductDiscountSubsidy::getDiscountPlanId, productDiscountPlan.getId())
                );
                //判断最高补贴金额，拿出制造商的金额
                BigDecimal maxdiscountAmt = BigDecimal.ZERO;
                List<ProductDiscountSubsidy> subsidyList = new ArrayList<>();
                for (ProductDiscountSubsidy productDiscountSubsidy : listProductDiscountSubsidy) {
                    //如果是方案时，需要命中规则得到最高补贴额
                    if (AfsEnumUtil.key(SubsidySideSelect.PLAN).equals(productDiscountSubsidy.getSingleSelect())) {
                        List<RuleResult> ruleRunResult = RuleHelper.runRule(json, productDiscountSubsidy.getDiscountRulePlanId().toString(), true, RuleRunEnum.SERIAL).getResults();//得到运行结果
                        if (ruleRunResult.size() > 0) {//空直接返回
                            //规则组结果转化
                            List ruleNoList = Lists.transform(ruleRunResult, (ruleResult) -> {
                                return ruleResult.getRuleNo();
                            });
                            //找到所有的适用规则信息
                            List<ProductRuleInfo> ruleInfoList = productRuleInfoService.list(Wrappers.<ProductRuleInfo>query().lambda()
                                    .eq(ProductRuleInfo::getFitScope, AfsEnumUtil.key(FitScope.DISCOUNTSUBSIDY))//适用场景=产品投放方案
                                    .in(ProductRuleInfo::getId, ruleNoList)//匹配规则组id
                            );
                            if (ruleInfoList.size() > 0) {//空直接返回
                                productDiscountSubsidy.setSubsidyMoney(ruleInfoList.get(0).getMoneyMax());//得到第一条的最高补贴金额
                            }
                        }
                    }
                    //判断制造商
                    if (productDiscountSubsidy.getSubsidySide().equals(AfsEnumUtil.key(SubsidySideType.MANUFACTURERS))) {
                        maxdiscountAmt = productDiscountSubsidy.getSubsidyMoney();
                    }
                    //列表处理
                    subsidyList.add(productDiscountSubsidy);
                }
                //贴息方案转map
                Map discountInfo = JSON.parseObject(JSON.toJSONString(productDiscountPlan), Map.class);
                discountInfo.put("maxdiscountAmt", maxdiscountAmt);//最高补贴金额
                discountInfo.put("subsidyList", subsidyList);//补贴方列表加入map
                //贴息信息整体加入主map
                map.put("discountInfo", discountInfo);
            }
            map.put("discountOption", discountType.getAtomValue());//贴息选择，0-无、1-正常贴息、2-灵活贴息
        }
        return map;
    }

    /**
     * @param discountType 还款方式
     * @param map          结果集
     * @return
     * @Description 判断是否存在尾款
     */
    public Map getIsTail(ProductPlanAtom discountType, Map map) {
        if (discountType != null) {
            //是否存在尾款
            String isTail = AfsEnumUtil.key(StatusEnum.NO);//否
            if (AfsEnumUtil.key(RepaymentType.BalanceLoan).equals(discountType.getAtomValue())) {
                isTail = AfsEnumUtil.key(StatusEnum.YES);
            }
            map.put("isTail", isTail);//是否存在尾款
        }
        return map;
    }

    /**
     * @param productPlanAtom 还款方式
     * @param discountType    贴息方式
     * @param map             结果集
     * @return
     * @Description 获取算法方式
     */
    public Map getAlgorithmType(ProductPlanAtom productPlanAtom, ProductPlanAtom discountType, Map map) {
        if (productPlanAtom != null) {
            //得到还款方式
            String repaymentType = productPlanAtom.getAtomValue();
            //算法方式
            String algorithmType = null;
            if (AfsEnumUtil.key(RepaymentType.BalanceLoan).equals(repaymentType) || AfsEnumUtil.key(RepaymentType.SegmentedLoan).equals(repaymentType)) {//尾款、分段；统一使用分段计算方式
                algorithmType = CalculateType.ballonloan.getValue();
            } else if (AfsEnumUtil.key(RepaymentType.ArbitraryLoan).equals(repaymentType)) {//任意贷；统一使用任意贷计算方式
                algorithmType = CalculateType.arbitraryloan.getValue();
            } else if (AfsEnumUtil.key(RepaymentType.InterestLoan).equals(repaymentType)) {//等额本息
                algorithmType = CalculateType.equalrental.getValue();
            } else if (AfsEnumUtil.key(RepaymentType.PrincipalLoan).equals(repaymentType)) {//等额本金
                algorithmType = CalculateType.equalprincipal.getValue();
            } else if (AfsEnumUtil.key(RepaymentType.StepLoan).equals(repaymentType)) {//阶梯贷,使用等比累进还款计算方式
                algorithmType = CalculateType.equalratioret.getValue();
            } else if (AfsEnumUtil.key(RepaymentType.AuspiciousLoan).equals(repaymentType)) {//吉祥贷；统一使用结构化计算方式
                algorithmType = CalculateType.structuredloan.getValue();
            }
            if (discountType != null) {
                //得到贴息方式
                String discountOption = discountType.getAtomValue();
                if ( AfsEnumUtil.key(DiscountCategory.Flexible).equals(discountOption)) {//灵活贴息单独处理
                    algorithmType = CalculateType.flexiblediscount.getValue();//灵活贴息
                }
            }
            map.put("algorithmType", algorithmType);//算法方式
        }
        return map;
    }

    /**
     * @param productPlanAtom 还款方式
     * @param map             结果集
     * @param productPlanId   产品ID
     * @return
     * @Description 还款方式参数数据
     */
    public Map getRepaymentData(ProductPlanAtom productPlanAtom, Map map, Long productPlanId) {
        if (productPlanAtom != null) {
            //还款方式参数数据
            ProductPlanRepay method = productPlanRepayService.getOne(Wrappers.<ProductPlanRepay>query().lambda()
                            .eq(ProductPlanRepay::getProductPlanId, productPlanId)
                    , false
            );
            if (method != null) {
                //阶梯贷,特殊处理阶梯贷浮动比例,(浮动比例=原值/100+1)
                if (AfsEnumUtil.key(RepaymentType.StepLoan).equals(productPlanAtom.getAtomValue())) {
                    JSONObject repaymentMethodData = JSONObject.parseObject(method.getRepaymentMethodData());
                    JSONObject repaymentMethods = (JSONObject) repaymentMethodData.get("repaymentMethods");
                    Double floatingProportionStepLoan = Double.parseDouble(repaymentMethods.get("floatingProportionStepLoan").toString());
                    floatingProportionStepLoan = floatingProportionStepLoan / 100 + 1;
                    repaymentMethods.put("floatingProportionStepLoan", floatingProportionStepLoan);
                    repaymentMethodData.put("repaymentMethods", repaymentMethods);
                    method.setRepaymentMethodData(repaymentMethodData.toJSONString());
                }
                JSONObject object = JSONObject.parseObject(StringUtils.isEmpty(method.getRepaymentMethodData()) ? "{}" : method.getRepaymentMethodData());

                map.put("repaymentData", object);//还款方式参数数据
            }
        }
        return map;
    }

    /**
     * @param zoneList
     * @return
     * @Description list转tree
     */
    public static List<ExtrasProgramInfoVo> buildTree(List<ExtrasProgramInfoVo> zoneList) {
        Map<String, List<ExtrasProgramInfoVo>> zoneByParentIdMap = zoneList.stream().collect(Collectors.groupingBy(ExtrasProgramInfoVo::getFatherNo));
        zoneList.forEach(zone -> zone.sonList = zoneByParentIdMap.get(zone.extrasProjectNo));
        return zoneList.stream().filter(v -> v.fatherNo.equals("0")).collect(Collectors.toList());//默认查询0层级
    }

    public IResponse saveOrUpdate(ProductPrototypeCondition prototypeCondition) {
        ProductPlan plan = prototypeCondition.getProductPlan();
        if (plan.getId() != null && AfsEnumUtil.key(StatusEnum.NO).equals(plan.getIsModel())) {
            ProductPlan planhis = this.getById(prototypeCondition.getProductPlan().getId());
            if (!AfsEnumUtil.key(ProductOnlineStatus.TEMPORARY_STORAGE).equals(planhis.getStatus()) && !AfsEnumUtil.key(ProductOnlineStatus.TAKE_EFFECT).equals(planhis.getStatus()))
                throw new AfsBaseException("产品不可修改！");
        } else if (plan.getId() != null && AfsEnumUtil.key(StatusEnum.YES).equals(plan.getIsModel())) {
            if (prototypeCondition.getProductPlan().getId() != null) {
                ProductPlan planhis = this.getById(prototypeCondition.getProductPlan().getId());
                Assert.isTrue(!AfsEnumUtil.key(ProductOnlineStatus.TAKE_EFFECT).equals(planhis.getStatus()), "产品生效不可修改！");
            }
        }
        String msg = this.checkPlan(plan);
        if (msg != null)
            throw new AfsBaseException(msg);
        if (!AfsEnumUtil.key(ProductOnlineStatus.TEMPORARY_STORAGE).equals(plan.getStatus())) {
            checkRule(prototypeCondition);
        }
        int count = this.count(Wrappers.<ProductPlan>query().lambda().eq(ProductPlan::getProductName, plan.getProductName()).eq(ProductPlan::getIsModel, plan.getIsModel()).ne(plan.getId() != null, ProductPlan::getId, plan.getId()));
        Assert.isTrue(count < 1, "产品名称[" + plan.getProductName() + "]重复");
        if (plan.getId() == null) {
            plan.setVersionNumber(1);
            plan.setCreateBy(null);
            plan.setCreateTime(null);
            plan.setUpdateTime(null);
            plan.setUpdateBy(null);
            ProductTemplate productTemplate = templateService.getById(plan.getProductTemplateId());
            Assert.isTrue(productTemplate != null, "模板不存在！");
            plan.setTemplateCategory(productTemplate.getTemplateCategory());
            //获取编号
            if(StringUtils.isEmpty(plan.getProductNumber())){
                String planNo = null;
                if(AfsEnumUtil.key(TemplateCategory.Father).equals(plan.getTemplateCategory()) && AfsEnumUtil.key(StatusEnum.YES).equals(plan.getIsModel())){
                    Long seqno = afsSequenceGenerator.genNext(AfsEnumUtil.key(StatusType.PRODUCT_NUM_YX), StatusType.PRODUCT_NUM_YX.toString());
                    planNo = AfsEnumUtil.key(StatusType.PRODUCT_NUM_YX) + DateUtil.year(DateUtil.date()) +StringUtils.leftPad(String.valueOf(seqno), 4, '0');// 编号
                }else if(AfsEnumUtil.key(TemplateCategory.Son).equals(plan.getTemplateCategory()) && AfsEnumUtil.key(StatusEnum.YES).equals(plan.getIsModel())){
                    Long seqno = afsSequenceGenerator.genNext(AfsEnumUtil.key(StatusType.PRODUCT_NUM_YXS), StatusType.PRODUCT_NUM_YXS.toString());
                    planNo = AfsEnumUtil.key(StatusType.PRODUCT_NUM_YXS) + DateUtil.year(DateUtil.date()) +StringUtils.leftPad(String.valueOf(seqno), 4, '0');// 编号
                }else if(AfsEnumUtil.key(TemplateCategory.Father).equals(plan.getTemplateCategory()) && AfsEnumUtil.key(StatusEnum.NO).equals(plan.getIsModel())){
                    Long seqno = afsSequenceGenerator.genNext(AfsEnumUtil.key(StatusType.PRODUCT_NUM_PD), StatusType.PRODUCT_NUM_PD.toString());
                    planNo = AfsEnumUtil.key(StatusType.PRODUCT_NUM_PD) + DateUtil.year(DateUtil.date()) +StringUtils.leftPad(String.valueOf(seqno), 4, '0');// 编号
                }else if(AfsEnumUtil.key(TemplateCategory.Son).equals(plan.getTemplateCategory()) && AfsEnumUtil.key(StatusEnum.NO).equals(plan.getIsModel())){
                    Long seqno = afsSequenceGenerator.genNext(AfsEnumUtil.key(StatusType.PRODUCT_NUM_PDS), StatusType.PRODUCT_NUM_PDS.toString());
                    planNo = AfsEnumUtil.key(StatusType.PRODUCT_NUM_PDS) + DateUtil.year(DateUtil.date()) +StringUtils.leftPad(String.valueOf(seqno), 4, '0');// 编号
                }
                plan.setProductNumber(planNo);
            }
            this.save(plan);
            if (!AfsEnumUtil.key(StatusEnum.YES).equals(productTemplate.getTemplateIsReference())) {
                productTemplate.setTemplateIsReference(AfsEnumUtil.key(StatusEnum.YES));
                templateService.updateById(productTemplate);
            }
            productPlanAtomService.saveOrUpdate(prototypeCondition.getJson(), plan.getId(), "new");
            productPlanAtomService.saveOrUpdate(prototypeCondition.getPostLoan(), plan.getId(), "new");
        } else {
            count = this.count(Wrappers.<ProductPlan>query().lambda().eq(ProductPlan::getProductNumber, plan.getProductNumber()).eq(ProductPlan::getIsModel, plan.getIsModel()).ne(plan.getId() != null, ProductPlan::getId, plan.getId()));
            Assert.isTrue(count < 1, "产品编号[" + plan.getProductNumber() + "]重复");
            this.updateById(plan);
            productPlanAtomService.saveOrUpdate(prototypeCondition.getJson(), plan.getId(), "update");
            productPlanAtomService.saveOrUpdate(prototypeCondition.getPostLoan(), plan.getId(), "update");
        }
        saveProductInformation(prototypeCondition, plan);
        return null;
    }

    @Override
    public void sendAlterDealerMq(Long id) {
        try{
            ProductPlan productPlan = this.getById(id);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("ID",id.toString());
            jsonObject.put("TableCode",AfsEnumUtil.key(StatusType.FNPRODUCT));
            jsonObject.put("Action",AfsEnumUtil.key(StatusType.ADD));

            StringBuffer xml = new StringBuffer();
            xml.append("<DATA>");
            xml.append("<NAME>");
            xml.append(productPlan.getProductName());
            xml.append("</NAME>");
            xml.append("<CODE>");
            xml.append(id.toString());
            xml.append("</CODE>");
            xml.append("<FNGROUP>");
            xml.append(AfsEnumUtil.key(StatusType.FNGROUP));
            xml.append("</FNGROUP>");
            xml.append("</DATA>");
            jsonObject.put("Data",xml.toString());
            commissionSystemSender.sendAlterDealer(jsonObject.toJSONString());
        }catch (Exception e){
            logger.info("佣金系统MQ发送消息失败："+e);
        }
    }

    /**
     * 产品批量下线定时任务
     */
    @Override
    public void timingTaskProductOffline() {
        this.update(Wrappers.<ProductPlan>lambdaUpdate()
                .le(ProductPlan::getEndTime, DateUtil.beginOfDay(DateUtil.date()))//结束时间小于等于当前时间
                .like(ProductPlan::getStatus, AfsEnumUtil.key(ProductOnlineStatus.GO_ONLINE))//状态等于上线
                .set(ProductPlan::getStatus,  AfsEnumUtil.key(ProductOnlineStatus.OFFLINE))//状态修改为下线
        );
    }

    //产品方案校验
    public String checkPlan(ProductPlan plan) {
        if (StrUtil.isNotBlank(plan.getExtrasPlanName())) {
            ExtrasProgramInfo extrasProgramInfo = extrasProgramService.getById(plan.getExtrasPlanId());
            if (extrasProgramInfo == null || !AfsEnumUtil.key(StatusEnum.YES).equals(extrasProgramInfo.getStatus()))
                return "附加贷方案不存在!";
        }
        if (StrUtil.isNotBlank(plan.getDiscountPlanName())) {
            ProductDiscountPlan discountPlan = productDiscountPlanService.getById(plan.getDiscountPlanId());
            if (discountPlan == null || !AfsEnumUtil.key(StatusEnum.YES).equals(discountPlan.getStatus()))
                return "贴息方案名称不存在!";
        }
        if (StrUtil.isNotBlank(plan.getFinancePlanName())) {
            SchemeFinance financePlan = financePlanService.getById(plan.getFinancePlanId());
            if (financePlan == null || !AfsEnumUtil.key(StatusEnum.YES).equals(financePlan.getStatus()))
                return "融资校验方案不存在!";
        }
        if (StrUtil.isNotBlank(plan.getRiskPlanName())) {
            SchemeRisk riskPlan = planService.getById(plan.getRiskPlanId());
            if (riskPlan == null || !AfsEnumUtil.key(StatusEnum.YES).equals(riskPlan.getStatus()))
                return "风险定价方案未生效!";
        }
        if (StrUtil.isNotBlank(plan.getLaunchPlanName())) {
            SchemeLaunch launchPlan = launchPlanService.getById(plan.getLaunchPlanId());
            if (launchPlan == null || !AfsEnumUtil.key(StatusEnum.YES).equals(launchPlan.getStatus()))
                return "产品投放方案未生效!";
        }
        return null;
    }

    private String saveProductInformation(ProductPrototypeCondition prototypeCondition, ProductPlan plan) {
        ProductPlanRepay method = productPlanRepayService.getOne(Wrappers.<ProductPlanRepay>query().lambda().eq(ProductPlanRepay::getProductPlanId, plan.getId()), false);
        if (method != null && prototypeCondition.getMethodParametersForm() != null) {
            method.setRepaymentMethod(prototypeCondition.getRepaymentMethod());
            method.setRepaymentMethodData(prototypeCondition.getMethodParametersForm().toString());
            productPlanRepayService.updateById(method);
        } else if (method != null && prototypeCondition.getMethodParametersForm() == null) {
            productPlanRepayService.removeById(method.getId());
        } else if (method == null && prototypeCondition.getMethodParametersForm() != null) {
            method = new ProductPlanRepay();
            method.setProductPlanId(plan.getId());
            method.setRepaymentMethod(prototypeCondition.getRepaymentMethod());
            method.setRepaymentMethodData(prototypeCondition.getMethodParametersForm().toString());
            productPlanRepayService.save(method);
        }
        productPlanRateService.updateProductPlanRate(prototypeCondition.getPlanRatejson(), plan.getId());
        return null;
    }

    //特定的校验
    private void checkRule(ProductPrototypeCondition prototypeCondition) {
        Map<String, Object> map = (HashMap) prototypeCondition.getJson();
        //最小贷期
        if (map.get("loanPeriodMin") == null)
            return;
        int loanPeriodMin = (int) map.get("loanPeriodMin");
        //最大贷期
        if (map.get("loanPeriodMax") == null)
            return;
        int loanPeriodMax = (int) map.get("loanPeriodMax");
        Assert.isTrue(loanPeriodMax >= loanPeriodMin, "最小贷期不能大于最大贷期！");

        //客户利率
        List<ProductPlanRate> productPlanRateList = prototypeCondition.getPlanRatejson();
        if (productPlanRateList.size() == 0) {
            Assert.isTrue(false, "请填写客户利率！");
        }

        List<Integer> loanPeriodList = new ArrayList();
        for (ProductPlanRate productPlanRate : productPlanRateList) {
            Assert.isTrue(loanPeriodMin <= productPlanRate.getLoanPeriodStart(), "客户利率：贷款期数起不能小于最小贷期！");
            Assert.isTrue(loanPeriodMax >= productPlanRate.getLoanPeriodEnd(), "客户利率：贷款期数止不能大于最大贷期！");

            int loanPeriodEnd = productPlanRate.getLoanPeriodEnd();
            for(int loanPeriodStart = productPlanRate.getLoanPeriodStart();loanPeriodStart<=loanPeriodEnd;loanPeriodStart++){
                loanPeriodList.add(loanPeriodStart);
            }
        }
        for (int i = 0; i < loanPeriodList.size() - 1; i++) {
            for (int j = 1; j < loanPeriodList.size() - i; j++) {
                Integer a;
                if ((loanPeriodList.get(j - 1)).compareTo(loanPeriodList.get(j)) > 0) { // 比较两个整数的大小
                    a = loanPeriodList.get(j - 1);
                    loanPeriodList.set((j - 1), loanPeriodList.get(j));
                    loanPeriodList.set(j, a);
                }
            }
        }
        Set<Integer> stringSet=new HashSet<>(loanPeriodList);
        if (loanPeriodList.size() != stringSet.size()) {
            Assert.isTrue(false, "客户利率：贷款期数不可重复！");
        }
        Assert.isTrue(loanPeriodMin == loanPeriodList.get(0), "客户利率：贷款期数没有覆盖全部贷期！");
        Assert.isTrue(loanPeriodMax == loanPeriodList.get(loanPeriodList.size()-1), "客户利率：贷款期数没有覆盖全部贷期！");
        int start = loanPeriodList.get(0);
        for(int i = 0;i<loanPeriodList.size();i++){
            if(start+i!=loanPeriodList.get(i)){
                Assert.isTrue(false, "客户利率：贷款期数没有覆盖全部贷期！");
            }
        }

        //分段贷
        if (prototypeCondition.getMethodParametersForm() != null && AfsEnumUtil.key(RepaymentType.SegmentedLoan).equals(prototypeCondition.getRepaymentMethod())) {
            JSONArray jsonArray = prototypeCondition.getMethodParametersForm().getJSONArray("data");
            if (ObjectUtils.isNotEmpty(jsonArray) && jsonArray.size() > 0) {
                int proportionRepaymentSections = 0;
                for (int i = 0; i < jsonArray.size(); i++) {
                    //分段还款期数
                    Integer numberInstallments = Integer.valueOf(jsonArray.getJSONObject(i).getString("numberInstallments"));
                    Assert.isTrue(numberInstallments != null, "分段还款期数不能为空！");
                    Assert.isTrue(numberInstallments <= loanPeriodMin, "分段还款期数不能大于最小贷期！");

                    if(Integer.valueOf(jsonArray.getJSONObject(i).getString("paymentByStages"))==0){//还款方式为比例
                        proportionRepaymentSections += Integer.valueOf(jsonArray.getJSONObject(i).getString("proportionRepaymentSections"));
                    }
                }
                Assert.isTrue(proportionRepaymentSections<100, "分段还款比例不能大于100！");
            }
        }
        //任意贷
        if (prototypeCondition.getMethodParametersForm() != null && AfsEnumUtil.key(RepaymentType.ArbitraryLoan).equals(prototypeCondition.getRepaymentMethod())) {
            JSONObject jSONObject = prototypeCondition.getMethodParametersForm().getJSONObject("repaymentMethods");
            map = JSON.parseObject(JSON.toJSONString(jSONObject), Map.class);
            if (map.get("setAnyNumberCredits") == null)
                return;
            int setAnyNumberCredits = (int) map.get("setAnyNumberCredits");
            Assert.isTrue(setAnyNumberCredits < loanPeriodMin, "任意贷期数不能大于最小贷期！");
        }
        //结构化
        if (prototypeCondition.getMethodParametersForm() != null && AfsEnumUtil.key(RepaymentType.AuspiciousLoan).equals(prototypeCondition.getRepaymentMethod())) {
            JSONObject jSONObject = prototypeCondition.getMethodParametersForm().getJSONObject("repaymentMethods");
            map = JSON.parseObject(JSON.toJSONString(jSONObject), Map.class);
            if (map.get("setAnyNumberCredits") == null)
                return;
            int setAnyNumberCredits = (int) map.get("setAnyNumberCredits");//结构化期数
            Assert.isTrue(loanPeriodMin == loanPeriodMax, "结构化中最小贷期必须等于最大贷期！");
            Assert.isTrue(setAnyNumberCredits < loanPeriodMin, "结构化期数不能大于贷期！");

        }
        //等额本息
        // 主产品含有附加贷—>附加贷中有子产品->利率类型与主产品利率类型一致、子产品贴息类型与贴息类型利率类型一致
        if (prototypeCondition.getMethodParametersForm() != null && AfsEnumUtil.key(RepaymentType.InterestLoan).equals(prototypeCondition.getRepaymentMethod())) {
            ProductPlan plan = prototypeCondition.getProductPlan();
            if (StrUtil.isNotBlank(plan.getExtrasPlanName()) && AfsEnumUtil.key(TemplateCategory.Father).equals(plan.getTemplateCategory())) {
                ExtrasProgramInfo extrasProgramInfo = extrasProgramService.getById(plan.getExtrasPlanId());
                if (AfsEnumUtil.key(StatusEnum.YES).equals(extrasProgramInfo.getIsProduct())) {//子产品是否为空
                    //子产品ID
                    Long sonProductPlanId = extrasProgramInfo.getProductPlanId();
                    Map<String, Object> mapJson = (Map<String, Object>) prototypeCondition.getJson();
                    Map<String, Object> mapLoan = (Map<String, Object>) prototypeCondition.getPostLoan();
                    if (mapLoan != null) {
                        mapJson.putAll(mapLoan);
                    }
                    if (mapJson != null && mapJson.containsKey(AfsEnumUtil.key(ProductAtomEnum.RATETYPE))) {// 利率
                        String rateType = String.valueOf(mapJson.get(AfsEnumUtil.key(ProductAtomEnum.RATETYPE)));
                        ProductPlanAtom sonRateType = productPlanAtomService.getProductPlanData(sonProductPlanId, AfsEnumUtil.key(ProductAtomEnum.RATETYPE));
                        Assert.isTrue(rateType.equals(sonRateType.getAtomValue()), "子产品利率类型与主产品利率类型不一致");
                    }
                    if (mapJson != null && mapJson.containsKey(AfsEnumUtil.key(ProductAtomEnum.DISCOUNTTYPE))) {// 贴息类型
                        String discountType = String.valueOf(mapJson.get(AfsEnumUtil.key(ProductAtomEnum.DISCOUNTTYPE)));
                        ProductPlanAtom sonDiscountType = productPlanAtomService.getProductPlanData(sonProductPlanId, AfsEnumUtil.key(ProductAtomEnum.DISCOUNTTYPE));
//                        Assert.isTrue(discountType.equals(sonDiscountType.getAtomValue()), "子产品贴息类型与主产品贴息类型不一致");
                    }
                }
            }
        }
        ProductPlan plan = prototypeCondition.getProductPlan();

        Map<String, Object> mapJson = (Map<String, Object>) prototypeCondition.getJson();
        Map<String, Object> mapLoan = (Map<String, Object>) prototypeCondition.getPostLoan();
        if (mapLoan != null) {
            mapJson.putAll(mapLoan);
        }
        String repaymentType = String.valueOf(mapJson.get(AfsEnumUtil.key(ProductAtomEnum.REPAYMENTTYPE)));
        String rateType = String.valueOf(mapJson.get(AfsEnumUtil.key(ProductAtomEnum.RATETYPE)));
        String discountType = String.valueOf(mapJson.get(AfsEnumUtil.key(ProductAtomEnum.DISCOUNTTYPE)));
        String isRiskPricing = String.valueOf(mapJson.get(AfsEnumUtil.key(ProductAtomEnum.ISRISKPRICING)));
        if (AfsEnumUtil.key(TemplateCategory.Father).equals(plan.getTemplateCategory())) {//主产品
            // 2 分段贷  4 阶梯贷 5 任意贷 6 结构化 ，利率为固定
            if (productParmsConfig.getRepaymentType_2().equals(repaymentType) || productParmsConfig.getRepaymentType_4().equals(repaymentType) || productParmsConfig.getRepaymentType_5().equals(repaymentType) || productParmsConfig.getRepaymentType_6().equals(repaymentType)) {
                if (StringUtils.isNotBlank(rateType)) {
                    Assert.isTrue(productParmsConfig.getRateType_0().equals(rateType), "还款方式：分段贷、阶梯贷、任意贷、结构化，利率为固定");
                }
            }
            // 1 等额本金  2 分段贷  4 阶梯贷  6 结构化  贴息类别为0 不贴息  1 贴息
            if (productParmsConfig.getRepaymentType_1().equals(repaymentType) || productParmsConfig.getRepaymentType_2().equals(repaymentType) || productParmsConfig.getRepaymentType_4().equals(repaymentType) || productParmsConfig.getRepaymentType_6().equals(repaymentType)) {
                if (StringUtils.isNotBlank(discountType)) {
                    Assert.isTrue(productParmsConfig.getDiscountType_0().equals(discountType) || productParmsConfig.getDiscountType_1().equals(discountType),
                            "还款方式：等额本金、分段贷、阶梯贷、结构化，贴息类别为不贴息、贴息");
                }
            }
            // 还款方式为 5 任意贷  贴息类别为0 不贴息
            if (productParmsConfig.getRepaymentType_5().equals(repaymentType)) {
                if (StringUtils.isNotBlank(discountType)) {
                    Assert.isTrue(productParmsConfig.getDiscountType_0().equals(discountType),
                            "还款方式：任意贷化，贴息类别为不贴息");
                }
            }
            //利率类型为浮动时，还款方式为 0 等额本息  1 等额本金  3 尾款贷 和贴息类别为不贴息
            if (productParmsConfig.getRateType_1().equals(rateType)) {
                if (StringUtils.isNotBlank(repaymentType)) {
                    Assert.isTrue(productParmsConfig.getRepaymentType_0().equals(repaymentType) || productParmsConfig.getRepaymentType_1().equals(repaymentType)
                                    || productParmsConfig.getRepaymentType_3().equals(repaymentType),
                            "利率类型为浮动时,还款方式：等额本息、等额本金、尾款贷");
                }
                if (StringUtils.isNotBlank(discountType)) {
                    Assert.isTrue(productParmsConfig.getDiscountType_0().equals(discountType),
                            "利率类型为浮动时，贴息类别为不贴息");
                }
            }
            ////贴息类别：1 贴息时 还款方式为 0 等额本息  1 等额本金  3 尾款贷 2 分段贷  4 阶梯贷   6 结构贷和 利率类型设为固定
            if (productParmsConfig.getDiscountType_1().equals(discountType)) {
                if (StringUtils.isNotBlank(repaymentType)) {
                    Assert.isTrue(productParmsConfig.getRepaymentType_0().equals(repaymentType) || productParmsConfig.getRepaymentType_1().equals(repaymentType)
                                    || productParmsConfig.getRepaymentType_2().equals(repaymentType) || productParmsConfig.getRepaymentType_3().equals(repaymentType) || productParmsConfig.getRepaymentType_4().equals(repaymentType)
                                    || productParmsConfig.getRepaymentType_6().equals(repaymentType),
                            "贴息类别：贴息时,还款方式：等额本息、等额本金、分段贷、尾款贷、阶梯贷、结构贷");
                }
                if (StringUtils.isNotBlank(rateType)) {
                    Assert.isTrue(productParmsConfig.getRateType_0().equals(rateType),
                            "贴息类别：贴息时，利率类型为固定");
                }
                if (StringUtils.isNotBlank(isRiskPricing)) {
                    Assert.isTrue(productParmsConfig.getIsRiskPricing_0().equals(isRiskPricing),
                            "贴息类别：贴息时，是否风险定价为否");
                }
            }
            //灵活贴息时，等额本息 尾款贷 和利率类型设为固定
            else if (productParmsConfig.getDiscountType_2().equals(discountType)) {
                if (StringUtils.isNotBlank(repaymentType)) {
                    Assert.isTrue(productParmsConfig.getRepaymentType_0().equals(repaymentType) || productParmsConfig.getRepaymentType_3().equals(repaymentType),
                            "贴息类别：灵活贴息时,还款方式：等额本息、尾款贷");
                }
                if (StringUtils.isNotBlank(rateType)) {
                    Assert.isTrue(productParmsConfig.getRateType_0().equals(rateType),
                            "贴息类别：灵活贴息时，利率类型为固定");
                }
                if (StringUtils.isNotBlank(isRiskPricing)) {
                    Assert.isTrue(productParmsConfig.getIsRiskPricing_0().equals(isRiskPricing),
                            "贴息类别：灵活贴息时，是否风险定价为否");
                }
            }

        } else {
            //子产品
            //利率类型为浮动时，贴息类别为不贴息
            if (productParmsConfig.getRateType_1().equals(rateType)) {
                if (StringUtils.isNotBlank(discountType)) {
                    Assert.isTrue(productParmsConfig.getDiscountType_0().equals(discountType),
                            "利率类型为浮动时，贴息类别为不贴息");
                }
            }
            if (productParmsConfig.getDiscountType_1().equals(discountType)) {
                if (StringUtils.isNotBlank(rateType)) {
                    Assert.isTrue(productParmsConfig.getRateType_0().equals(rateType),
                            "贴息类别：贴息时，利率类型为固定");
                }
            }

        }
    }
}
